import matplotlib.pyplot as plt
import seaborn as sns
from pyecharts.charts import Bar
from pyecharts.faker import Faker
import pyecharts.options as opts
from pyecharts.charts import Scatter3D, Line, Scatter


def draw_distribution_histogram(data, path, x_label, y_label, title,
                                is_kde=True, color1="yellow", color2="orange"):
    """

    bins: 设置直方图条形的数目
    is_hist: 是否绘制直方图
    is_kde: 是否绘制核密度图
    is_rug: 是否绘制生成观测数值的小细条
    is_vertical: 如果为True，观察值在y轴上
    is_norm_hist: 如果为True，直方图高度显示一个密度而不是一个计数，如果kde设置为True，则此参数一定为True
    """
    sns.set()  # 切换到sns的默认运行配置
    sns.histplot(data, bins=40, kde=is_kde, stat='probability',
                 cumulative=True, color=color1, alpha=0.5, multiple='dodge')
    sns.histplot(data, bins=40, kde=is_kde, stat='probability', color=color2, multiple='dodge')
    # 添加x轴和y轴标签
    plt.xlabel(x_label)
    plt.ylabel(y_label)

    # 添加标题
    plt.title(title)
    plt.tight_layout()  # 处理显示不完整的问题
    plt.savefig(path, dpi=300)
    plt.close()


def draw_hist(value_name, value, title, axis_label, saving_path=0):
    c = (
        Bar()
        .add_xaxis([i for i in range(len(value[0]))])
        .add_yaxis(value_name[0], value[0])
        .add_yaxis(value_name[1], value[1])
        .add_yaxis(value_name[2], value[2])
        .set_global_opts(
            title_opts=opts.TitleOpts(title=title),
            yaxis_opts=opts.AxisOpts(name=axis_label[0]),
            xaxis_opts=opts.AxisOpts(name=axis_label[1]),
            datazoom_opts=[
                opts.DataZoomOpts(
                    is_show=True,
                    is_realtime=True,
                    start_value=30,
                    end_value=70,
                    xaxis_index=[0, 1],
                )]
        )
        .render(saving_path)
    )


# 绘制折线图
def draw_line(x_axis, y_axis, y_axis_name, saving_path, page_title, mode, title):
    scatter = Line(init_opts=opts.InitOpts(width="1600px", height="650px", page_title=page_title))
    if mode == 'one_x_axis':
        scatter.add_xaxis(xaxis_data=x_axis)
    for i in range(len(y_axis_name)):
        if mode != 'one_x_axis':
            scatter.add_xaxis(xaxis_data=x_axis[i])
        scatter.add_yaxis(
            series_name=y_axis_name[i],
            y_axis=y_axis.iloc[:, i],
            markpoint_opts=opts.MarkPointOpts(
                data=[
                    opts.MarkPointItem(type_="max", name="最大值"),
                ]
            ),
            markline_opts=opts.MarkLineOpts(
                data=[opts.MarkLineItem(type_="average", name="平均值")]
            ),
        )

    scatter.set_global_opts(
        title_opts=opts.TitleOpts(title=title, subtitle="横坐标归一化"),
        tooltip_opts=opts.TooltipOpts(trigger="axis"),
        toolbox_opts=opts.ToolboxOpts(is_show=True),
        xaxis_opts=opts.AxisOpts(type_="value", boundary_gap=False),
        datazoom_opts=[
            opts.DataZoomOpts(
                is_show=True,
                is_realtime=True,
                start_value=30,
                end_value=70,
                xaxis_index=[0, 1],
            )]
    )
    scatter.render(saving_path)


def draw_3D_scatter(data, series_name, color, axis_range, page_title, title, saving_path):
    scatter = Scatter3D(init_opts=opts.InitOpts(width="1600px", height="650px", page_title=page_title))
    for i in zip(data, series_name, color):
        # 添加散点数据，其中每个元组代表一个点的 (x, y, z) 坐标
        scatter.add(
            i[1],  # 系列名称
            i[0],  # 数据，需要转换为列表的列表形式，这里使用 zip(*data) 来转置数据
            grid3d_opts=opts.Grid3DOpts(width=100, height=100, depth=100),
            xaxis3d_opts=opts.Axis3DOpts(
                type_="value",  # 设置X轴的类型为数值型
                min_=-axis_range,  # 设置X轴的最小值
                max_=axis_range,  # 设置X轴的最大值
            ),
            yaxis3d_opts=opts.Axis3DOpts(
                type_="value",  # 设置Y轴的类型为数值型
                min_=-axis_range,  # 设置Y轴的最小值
                max_=axis_range,  # 设置Y轴的最大值
            ),
            zaxis3d_opts=opts.Axis3DOpts(
                type_="value",  # 设置Z轴的类型为数值型
                min_=-axis_range,  # 设置Z轴的最小值
                max_=axis_range,  # 设置Z轴的最大值
            ),
            itemstyle_opts=opts.ItemStyleOpts(
                border_width=0.5, border_color=i[2], color=i[2]  # 边框宽度，可以调整以改变点的大小视觉效果
            ),
        )
    # 设置全局配置项
    scatter.set_global_opts(
        title_opts=opts.TitleOpts(title=title),
    )
    # 渲染图表到 HTML 文件
    scatter.render(saving_path)


def draw_scatter(x_data, y_data, series_name, color, page_title, title, saving_path):
    """
    绘制pandas格式的数据
    :param x_data: 横坐标，pd的第一列
    :param y_data: 纵坐标，pd的其余列
    :param series_name: pd的其余几列的columns
    :param color:pd的其余几列的颜色
    :param page_title:标签页标题
    :param title:图表标题
    :param saving_path:保存路径
    :return:
    """
    # 创建散点图对象
    scatter = Scatter(init_opts=opts.InitOpts(width="1600px", height="650px", page_title=page_title))

    # 添加x轴和y轴数据，以及设置点的颜色
    scatter.add_xaxis(x_data)
    for i in zip(series_name, color):
        scatter.add_yaxis(
            series_name=i[0],
            y_axis=y_data[i[0]],
            symbol_size=5,  # 设置点的大小
            itemstyle_opts=opts.ItemStyleOpts(color=i[1]),  # 设置点的颜色
        )

    # 设置全局配置项
    scatter.set_global_opts(
        title_opts=opts.TitleOpts(title=title),  # 设置标题
        xaxis_opts=opts.AxisOpts(splitline_opts=opts.SplitLineOpts(is_show=True)),  # x轴配置项
        yaxis_opts=opts.AxisOpts(splitline_opts=opts.SplitLineOpts(is_show=True)),  # y轴配置项
        tooltip_opts=opts.TooltipOpts(trigger="axis"),
        toolbox_opts=opts.ToolboxOpts(is_show=True),
        datazoom_opts=[
            opts.DataZoomOpts(
                is_show=True,
                is_realtime=True,
                start_value=30,
                end_value=70,
                xaxis_index=[0, 1],
            )]
    )

    # 渲染成html文件
    scatter.render(saving_path)


if __name__ == '__main__':
    pass
